using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using DslCrossModelFramework.ModelTraversal;
using Microsoft.VisualStudio.Modeling;

namespace DslCrossModelFramework.ModelRelationship {
    public abstract class ModelRelationshipDefinition<TParentModelElement, TModelRootType> : IModelRelationshipDefinition
        where TParentModelElement : ModelElement
        where TModelRootType : ModelElement {

        public ModelRelationshipDefinition() {}

        public ModelRelationshipDefinition(IModelDirectory modelDirectory) {
            this.modelDirectory = modelDirectory;
        }

        public IModelDirectory ModelDirectory {
            get {
                return modelDirectory;
            }
        }
        private IModelDirectory modelDirectory;


        public CrossModelManager CrossModelManager {
            get { return crossModelManager; }
        }
        private CrossModelManager crossModelManager;

        public ReadOnlyCollection<ModelElement> GetChildModelElements(ModelPath parentPath, CrossModelManager crossModelManager, string scope) {
            this.crossModelManager = crossModelManager;
            if(parentPath.TargetModelElement is TParentModelElement) {
                List<ModelElement> modelElements = new List<ModelElement>();
                foreach (ModelElement element in this.GetChildElements(parentPath)) {
                    modelElements.Add(element);
                }
                return new ReadOnlyCollection<ModelElement>(modelElements);
            }
            else {
                throw new ArgumentException(string.Format("Type must be a {0}", typeof(TParentModelElement).FullName), "parentPath");
            }
        }

        public List<ModelPath> GetChildPaths(ModelPath parentPath, CrossModelManager manager, string scope) {
            ReadOnlyCollection<ModelElement> children = this.GetChildModelElements(parentPath, manager, scope);
            List<ModelPath> modelPaths = new List<ModelPath>();
            foreach (ModelElement child in children) {
                ModelPath newPath = parentPath.Clone() as ModelPath;
                newPath.Merge(new ModelPath(parentPath.TargetModelElement, child, scope));
                modelPaths.Add(newPath);
            }
            return modelPaths;
        }

        public Type ParentType {
            get { return typeof(TParentModelElement); }
            set { }
        }


        public Type ModelRootType {
            get { return typeof(TModelRootType); }
            set { }
        }

        public abstract ReadOnlyCollection<ModelElement> GetChildElements(ModelPath parentPath);
    }
}